home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianTextFiles.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
7KB
|
341 lines
/*ScianTextFiles.c
Eric Pepke
24 February 1993
Stuff for reading text files from SciAn
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianIDs.h"
#include "ScianTextFiles.h"
TextFilePtr allTextFiles = 0;
void InitTextFiles()
/*Initialize the text file system*/
{
allTextFiles = 0;
}
#ifdef PROTO
TextFilePtr OpenTextFile(char *name, TextFlagsTyp flags)
#else
TextFilePtr OpenTextFile(name, flags)
char *name;
TextFlagsTyp flags;
#endif
/*Opens a text file with name and flags. Returns it, or returns null.*/
{
FILE *filePtr;
TextFilePtr retVal;
if (flags & TF_READ)
{
filePtr = fopen(name, "r");
}
else
{
return NULL;
}
if (filePtr)
{
/*Create a text file structure*/
retVal = newp(TextFile);
if (!retVal)
{
OMErr();
return NULL;
}
/*Fill in stuff*/
retVal -> flags = flags;
retVal -> eof = 0;
retVal -> lineNum = 0;
retVal -> nAlloc = TEXTLINEALLOCCHUNK;
retVal -> curLine = Alloc(TEXTLINEALLOCCHUNK);
if (!retVal -> curLine)
{
Free(retVal);
return NULL;
}
retVal -> name = Alloc(strlen(name) + 1);
if (!retVal -> name)
{
Free(retVal -> curLine);
OMErr();
return NULL;
}
strcpy(retVal -> name, name);
retVal -> filePtr = filePtr;
retVal -> lineNum = 0;
/*Link to all and return*/
retVal -> next = allTextFiles;
allTextFiles = retVal;
return retVal;
}
else
{
return NULL;
}
}
#ifdef PROTO
void CloseTextFile(TextFilePtr textFile)
#else
void CloseTextFile(textFile)
TextFilePtr textFile;
#endif
/*Closes a text file*/
{
TextFilePtr *runner;
fclose(textFile -> filePtr);
Free(textFile -> name);
Free(textFile -> curLine);
runner = &allTextFiles;
while (*runner)
{
if (*runner == textFile)
{
(*runner) = (*runner) -> next;
}
else
{
runner = &((*runner) -> next);
}
}
Free(textFile);
}
#define MAXERROREND 75
#define ERRORPREVIOUS 30
#ifdef PROTO
void CurLineError(TextFilePtr textFile, char *message, char *beginning, char *end)
#else
void CurLineError(textFile, message, beginning, end)
TextFilePtr textFile;
char *message;
char *beginning;
char *end;
#endif
/*Prints to standard error an error message about reading file textFile.
message is a message to print or NULL. message should not contain
newline at the end.
beginning and end may point to the begin and end+1 of the portion of the
string where the error is, in which case the line or a portion of the
line will be printed, or they may be NULL*/
{
fprintf(stderr, "Error in file '%s' line %d%c\n",
textFile -> name, textFile -> lineNum,
(message || (beginning && end)) ? ':' : '.');
if (beginning && end)
{
/*Determine a good place to begin and end*/
char *s;
int column;
column = 0;
for (s = textFile -> curLine;
(*s) && (s < end) && (column < MAXERROREND);
++s)
{
++column;
if (*s == '\t') column = column - column % 8 + 8;
}
if (column < MAXERROREND)
{
/*Just print normally*/
/*Print the line first*/
column = 0;
for (s = textFile -> curLine;
(*s) && (*s != '\n') && column < MAXERROREND;
++s)
{
fputc(*s, stderr);
++column;
if (*s == '\t') column = column - column % 8 + 8;
}
if (*s && (*s != '\n'))
{
/*Not really the end, continuation*/
fprintf(stderr, "...\n");
}
else
{
fprintf(stderr, "\n");
}
/*Now print the stuff underneath*/
column = 0;
for (s = textFile -> curLine;
(*s) && (s < beginning);
++s)
{
fputc(*s == '\t' ? '\t' : ' ', stderr);
}
for (;
(*s) && (s < end);
++s)
{
fputc(*s == '\t' ? '\t' : '^', stderr);
}
fprintf(stderr, "\n");
}
else
{
/*Back off a little*/
}
}
if (message)
{
fprintf(stderr, "%s\n", message);
}
}
/*States for reading in text file*/
#define TFS_BOL 1 /*Beginning of line*/
#define TFS_NORMAL 2 /*Normal*/
#define TFS_MAYBECONT 3 /*May be a continuation*/
#define TFS_ANOTHERLINE 4 /*Must read another line*/
#ifdef PROTO
char *GetNextLine(TextFilePtr textFile)
#else
char *GetNextLine(textFile)
TextFilePtr textFile;
#endif
/*Advances to the next line and gets it, or NULL if file closed or EOF or
error*/
{
long nChars;
char *success;
int k;
int state;
if (!(textFile -> flags | TF_READ)) return NULL;
if (textFile -> eof) return NULL;
for (;;)
{
state = TFS_BOL;
nChars = 0;
do
{
/*Get a single line*/
success = fgets(tempStr, TEMPSTRSIZE, textFile -> filePtr);
if (!success && (state = TFS_BOL))
{
/*Must be an end of file*/
textFile -> eof = true;
break;
}
++textFile -> lineNum;
if (!success)
{
/*There must be nothing more in the line*/
break;
}
/*It's OK, add it to what's there*/
for (k = 0; tempStr[k]; ++k)
{
if (nChars > (textFile -> nAlloc - 2))
{
/*Expand buffer*/
textFile -> nAlloc += TEXTLINEALLOCCHUNK;
textFile -> curLine = Realloc(textFile -> curLine, textFile -> nAlloc);
if (!(textFile -> curLine))
{
OMErr();
return NULL;
}
}
if (tempStr[k] == '\n')
{
/*End of line*/
if (state == TFS_MAYBECONT)
{
/*It's a continuation line.*/
--nChars;
state = TFS_ANOTHERLINE;
break;
}
else if (textFile -> flags & TF_INCLUDENL)
{
textFile -> curLine[nChars++] = '\n';
state = TFS_NORMAL;
}
}
else if ((textFile -> flags & TF_CONTINUATION) &&
(tempStr[k] == '\\'))
{
/*It might be a continuation line*/
textFile -> curLine[nChars++] = '\\';
state = TFS_MAYBECONT;
}
else
{
textFile -> curLine[nChars++] = tempStr[k];
state = TFS_NORMAL;
}
}
} while (state == TFS_ANOTHERLINE);
/*Now the buffer has been filled. Figure out what to do with it.*/
if (textFile -> eof)
{
/*End of file was hit.*/
return NULL;
}
textFile -> curLine[nChars] = 0;
if ((textFile -> flags & TF_HASHCOMMENTS) &&
(textFile -> curLine[0] == '#'))
{
/*This is a comment. Don't do anything, just read another line*/
}
else
{
return textFile -> curLine;
}
}
}
#ifdef PROTO
char *GetCurLine(TextFilePtr textFile)
#else
char *GetCurLine(textFile)
TextFilePtr textFile;
#endif
/*Gets the current line. Returns NULL if file is closed or at EOF or error*/
{
if (!(textFile -> flags | TF_READ)) return NULL;
if (textFile -> eof) return NULL;
if (textFile -> lineNum == 0)
{
return GetNextLine(textFile);
}
return (textFile -> curLine);
}
void KillTextFiles()
/*Kill the text file system*/
{
TextFilePtr fileToClose;
while (allTextFiles)
{
fileToClose = allTextFiles;
allTextFiles = allTextFiles -> next;
CloseTextFile(fileToClose);
}
}